package com.example.core;

import com.baomidou.mybatisplus.annotation.TableName;
import com.example.annotation.AutoTable;
import com.example.annotation.TableColumn;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 表结构解析器
 */
@Component
public class TableParser {
    
    /**
     * 解析实体类，生成表信息
     */
    public TableInfo parse(Class<?> entityClass) {
        TableInfo tableInfo = new TableInfo();
        
        // 解析表名
        String tableName = parseTableName(entityClass);
        tableInfo.setTableName(tableName);
        
        // 解析表注释
        AutoTable autoTable = entityClass.getAnnotation(AutoTable.class);
        if (autoTable != null) {
            tableInfo.setComment(autoTable.comment());
        }
        
        // 解析字段
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            TableColumn tableColumn = field.getAnnotation(TableColumn.class);
            if (tableColumn != null) {
                TableInfo.ColumnInfo columnInfo = parseColumn(field, tableColumn);
                tableInfo.getColumns().add(columnInfo);
                
                // 解析索引
                if (tableColumn.index() || tableColumn.unique()) {
                    TableInfo.IndexInfo indexInfo = new TableInfo.IndexInfo();
                    indexInfo.setColumnName(columnInfo.getColumnName());
                    indexInfo.setUnique(tableColumn.unique());
                    indexInfo.setIndexName(generateIndexName(tableName, columnInfo.getColumnName(), tableColumn.unique()));
                    tableInfo.getIndexes().add(indexInfo);
                }
            }
        }
        
        return tableInfo;
    }
    
    /**
     * 解析表名
     */
    private String parseTableName(Class<?> entityClass) {
        // 优先使用 @AutoTable 注解
        AutoTable autoTable = entityClass.getAnnotation(AutoTable.class);
        if (autoTable != null && !autoTable.value().isEmpty()) {
            return autoTable.value();
        }
        
        // 其次使用 @TableName 注解
        TableName tableName = entityClass.getAnnotation(TableName.class);
        if (tableName != null && !tableName.value().isEmpty()) {
            return tableName.value();
        }
        
        // 最后使用类名转下划线
        return camelToUnderscore(entityClass.getSimpleName());
    }
    
    /**
     * 解析字段
     */
    private TableInfo.ColumnInfo parseColumn(Field field, TableColumn tableColumn) {
        TableInfo.ColumnInfo columnInfo = new TableInfo.ColumnInfo();
        
        // 字段名
        String columnName = tableColumn.value().isEmpty() ? 
                camelToUnderscore(field.getName()) : tableColumn.value();
        columnInfo.setColumnName(columnName);
        
        // 字段类型
        columnInfo.setColumnType(tableColumn.type());
        columnInfo.setLength(tableColumn.length());
        columnInfo.setScale(tableColumn.scale());
        
        // 其他属性
        columnInfo.setNullable(tableColumn.nullable());
        columnInfo.setDefaultValue(tableColumn.defaultValue());
        columnInfo.setComment(tableColumn.comment());
        columnInfo.setPrimaryKey(tableColumn.primaryKey());
        columnInfo.setAutoIncrement(tableColumn.autoIncrement());
        columnInfo.setUnique(tableColumn.unique());
        
        return columnInfo;
    }
    
    /**
     * 生成索引名
     */
    private String generateIndexName(String tableName, String columnName, boolean unique) {
        String prefix = unique ? "uk_" : "idx_";
        return prefix + tableName + "_" + columnName;
    }
    
    /**
     * 驼峰转下划线
     */
    private String camelToUnderscore(String camelCase) {
        if (camelCase == null || camelCase.isEmpty()) {
            return camelCase;
        }
        StringBuilder result = new StringBuilder();
        result.append(Character.toLowerCase(camelCase.charAt(0)));
        for (int i = 1; i < camelCase.length(); i++) {
            char ch = camelCase.charAt(i);
            if (Character.isUpperCase(ch)) {
                result.append('_');
                result.append(Character.toLowerCase(ch));
            } else {
                result.append(ch);
            }
        }
        return result.toString();
    }
}
